#include <iostream>
#include <stdlib.h>
#include <Windows.h> // 引入 Windows.h 头文件
#include <time.h>
#include<xmmintrin.h> //SSE
#include<emmintrin.h> //SSE2
#include<pmmintrin.h> //SSE3
#include<tmmintrin.h> //SSSE3
#include<smmintrin.h> //SSE4.1
#include<nmmintrin.h> //SSSE4.2
#include<immintrin.h> //AVX、AVX2
#include<iomanip>
#include<ctime>

using namespace std;

void special_avx(int n, int m, int* a, int** matr)
{
    int i, j, k;
    for (i = 0; i < n; i++)
    {
        int bpos = i / 32, spos = i % 32;
        if (a[bpos] >> (31 - spos) != 0)
        {
            if (matr[n - 1 - i][bpos] >> (31 - spos) == 0)
            {
                for (j = 0; j <= m - 8; j += 8)
                {
                    __m256i temp = _mm256_loadu_si256((__m256i*)(a + j));
                    _mm256_storeu_si256((__m256i*)(matr[n - 1 - i] + j), temp);
                }
                for (; j < m; j++)
                    matr[n - 1 - i][j] = a[j];
                return;
            }
            else
            {
                for (j = 0; j <= m - 8; j += 8)
                {
                    __m256i t1 = _mm256_loadu_si256((__m256i*)(matr[n - 1 - i] + j));
                    __m256i t2 = _mm256_loadu_si256((__m256i*)(a + j));
                    t2 = _mm256_xor_si256(t1, t2);
                    _mm256_storeu_si256((__m256i*)(a + j), t2);
                }
                for (; j < m; j++)
                    a[j] ^= matr[n - 1 - i][j];
            }
        }
    }
}

void special(int n, int m, int* a, int** matr)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        int bpos = i / 32, spos = i % 32;
        if (a[bpos] >> (31 - spos) != 0)
        {
            if (matr[n - 1 - i][bpos] >> (31 - spos) == 0)
            {
                for (j = 0; j < m; j++)
                    matr[n - 1 - i][j] = a[j];
                return;
            }
            else
            {
                for (j = 0; j < m; j++)
                    a[j] ^= matr[n - 1 - i][j];
            }
        }
    }
}

int init_matrix(int* a, int n, int m)
{
    for (int j = 0; j < m; j++) a[j] = 0;
    int q = (rand() % n) / 2;
    while (q == 0) q = (rand() % n) / 2;
    int p = n;
    int temp;
    for (int i = 0; i < q; i++)
    {
        if (p != 0)
        {
            p = rand() % p;
            if (i == 0)
                temp = p;
        }
        int bpos = p / 32, spos = p % 32;
        bpos = m - 1 - bpos;
        int ans = 1;
        ans = ans << spos;
        a[bpos] |= ans;
    }
    return temp;
}

int main()
{
    int n, m, u, l;
    srand(time(0));
    int test[20] = { 32, 64, 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048, 2176, 2304 };
    n = 32;
    for (int i = 0; i < 20; i++)
    {
        n = test[i];
        u = rand() % (n / 2);
        while (u == 0) u = rand() % (n / 2);
        l = rand() % n + n / 2;
        if (n % 32 == 0)
            m = n / 32;
        else
            m = n / 32 + 1;
        int** mc = new int* [n];
        int** mb = new int* [n];
        for (int i = 0; i < n; i++)
        {
            mc[i] = new int[m];
            mb[i] = new int[m];
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {
                mc[i][j] = 0;
                mb[i][j] = 0;
            }
        for (int i = 0; i < u; i++)
        {
            int* a1 = new int[m];
            int* a2 = new int[m];
            int temp = init_matrix(a1, n, m);
            for (int j = 0; j < m; j++)
                a2[j] = a1[j];
            for (int j = 0; j < m; j++)
            {
                mc[n - 1 - temp][j] = a1[j];
                mb[n - 1 - temp][j] = a2[j];
            }
        }

        LARGE_INTEGER tstart, tend, frequency;
        double timeUsed1 = 0.0, timeUsed2 = 0.0;

        for (int i = 0; i < l; i++)
        {
            int* a1 = new int[m];
            int* a2 = new int[m];
            int temp = init_matrix(a1, n, m);
            for (int j = 0; j < m; j++)
                a2[j] = a1[j];

            QueryPerformanceCounter(&tstart); // Windows高精度计时开始
            special(n, m, a1, mc);
            QueryPerformanceCounter(&tend); // Windows高精度计时结束
            QueryPerformanceFrequency(&frequency); // 获取计时器频率
            timeUsed1 += 1000000.0 * (tend.QuadPart - tstart.QuadPart) / frequency.QuadPart; // 计算耗时（微秒）

            QueryPerformanceCounter(&tstart); // Windows高精度计时开始
            special_avx(n, m, a2, mb);
            QueryPerformanceCounter(&tend); // Windows高精度计时结束
            timeUsed2 += 1000000.0 * (tend.QuadPart - tstart.QuadPart) / frequency.QuadPart; // 计算耗时（微秒）
        }
        cout << n << " " << timeUsed1 / timeUsed2 * 100 << "%" << endl;
    }
    return 0;
}
